home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Delphi Programmer's Power Pack
/
Delphi Volume 1.iso
/
s_to_z
/
tsmtp11
/
mime.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1996-09-15
|
12KB
|
544 lines
unit Mime;
interface
uses Classes,SysUtils,Forms,Dialogs;
const
MaxChars = 57;
type
TBinBytes = array[1..MaxChars] of byte;
TTxtBytes = array[1..2*MaxChars] of byte;
T24Bits = array[0..8*MaxChars] of boolean;
EUUInvalidCharacter = class(Exception)
constructor Create;
end;
EMIMEError = class(Exception);
{$IFDEF UseHuge}
TTextStream = class(TMemoryStream)
public
procedure Write(const s : string);
procedure Read(var s : string);
end;
{$ENDIF}
TBase64 = class
private
{$IFDEF UseHuge}
TextStream : TTextStream;
{$ELSE}
TextStream : TStringList;
{$ENDIF}
Stream : TStream;
CurSection : byte;
A24Bits : T24Bits;
FOnProgress : TNotifyEvent;
FOnStart : TNotifyEvent;
FOnEnd : TNotifyEvent;
function GenerateTxtBytes(tb : TBinBytes; NumOfBytes : byte) : string;
procedure GenerateBinBytes(InS : string; BufPtr : pointer;
var BytesGenerated : word);
function ByteFromTable(Ch : Char) : byte;
procedure DoProgress(Sender : TObject);
procedure DoStart(Sender : TObject);
procedure DoEnd(Sender : TObject);
public
Progress : Integer;
ProgressStep : Integer;
Canceled : boolean;
Table : string;
{$IFDEF UseHuge}
constructor Create(AStream : TStream; ATextStream : TTextStream);
{$ELSE}
constructor Create(AStream : TStream; ATextStream : TStringList);
{$ENDIF}
procedure Encode;
procedure Decode;
property OnProgress : TNotifyEvent read FOnProgress
write FOnProgress;
property OnStart : TNotifyEvent read FOnStart write FOnStart;
property OnEnd : TNotifyEvent read FOnEnd write FOnEnd;
end;
TQuotedPrintable = class(TComponent)
private
{ Private declarations }
protected
{ Protected declarations }
Stream : TStream;
Lines : TStringList;
procedure ReplaceHiChars(var s : string);
procedure ReplaceHex(var s : string);
procedure ReformatParagraph(Buf : PChar; Len : Integer;
TL : TStringList);
public
{ Public declarations }
Canceled : boolean;
constructor Create(AStream : TStream; ALines : TStringList);
procedure Encode;
procedure Decode;
published
{ Published declarations }
end;
function GetContentType(const FileName : string) : string;
function MakeUniqueID : string;
implementation
constructor EUUInvalidCharacter.Create;
begin
inherited Create('Invalid character in the input file');
end;
{$IFDEF UseHuge}
{TTextStream}
procedure TTextStream.Write(const s : string);
var
Buf : array[0..255] of Char;
sLen : byte absolute s;
begin
StrPCopy(@Buf,Concat(s,^M^J));
inherited Write(Buf,StrLen(@Buf));
end;
procedure TTextStream.Read(var s : string);
var
sLen : byte absolute s;
Ch : Char;
begin
Ch:=#00; s:='';
repeat
inherited Read(Ch,1);
if not (Ch in [^M,^J]) then
s:=Concat(s,Ch);
until Ch=^J;
end;
{$ENDIF}
{implementation for TBase64}
{$IFDEF UseHuge}
constructor TBase64.Create(AStream : TStream; ATextStream : TTextStream);
{$ELSE}
constructor TBase64.Create(AStream : TStream; ATextStream : TStringList);
{$ENDIF}
begin
inherited Create;
Stream:=AStream;
TextStream:=ATextStream;
ProgressStep:=10;
Table:='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
FillChar(A24Bits,SizeOf(A24Bits),0);
end;
procedure TBase64.DoProgress(Sender : TObject);
begin
if Assigned(FOnProgress) then
FOnProgress(Sender);
end;
procedure TBase64.DoStart(Sender : TObject);
begin
if Assigned(FOnStart) then
FOnStart(Sender);
end;
procedure TBase64.DoEnd(Sender : TObject);
begin
if Assigned(FOnEnd) then
FOnEnd(Sender);
end;
function TBase64.GenerateTxtBytes(tb : TBinBytes; NumOfBytes : byte) : string;
var
i,j,k,b,m : word;
s : string;
begin
k:=0;
FillChar(A24Bits,SizeOf(T24Bits),0);
for i:=1 to MaxChars do
begin
b:=tb[i];
for j:=7 DownTo 0 do
begin
m:=1 shl j;
if (b and m = m) then
A24Bits[k]:=true;
Inc(k);
end;
end;
s:=''; k:=0; m:=4*(MaxChars div 3);
for i:=1 to m do
begin
b:=0;
for j:=5 DownTo 0 do
begin
if A24Bits[k] then b:= b or (1 shl j);
Inc(k);
end;
s[i]:=Table[b+1];
end;
if (NumOfBytes=MaxChars) or (NumOfBytes mod 3=0) then
s[0]:=Char(4*NumOfBytes div 3)
else
begin
s[0]:=Char(4*NumOfBytes div 3+1);
while (Length(s) mod 4)<>0 do
s:=Concat(s,'=');
end;
Result:=s;
end;
procedure TBase64.Encode;
var
BytesRead : word;
ABinBytes : TBinBytes;
Total : LongInt;
begin
DoStart(Self);
TextStream.Clear;
Progress:=0; Total:=0; Canceled:=false;
try
repeat
FillChar(ABinBytes,SizeOf(TBinBytes),0);
BytesRead:=Stream.Read(ABinBytes,MaxChars);
Inc(Total,BytesRead);
{$IFDEF UseHuge}
TextStream.Write(GenerateTxtBytes(ABinBytes,BytesRead));
{$ELSE}
TextStream.Add(GenerateTxtBytes(ABinBytes,BytesRead));
{$ENDIF}
Progress:=Round(100*Total/Stream.Size);
if Progress mod ProgressStep = 0 then
DoProgress(Self);
Application.ProcessMessages;
until (BytesRead<MaxChars) or Canceled;
finally
Progress:=100;
DoProgress(Self);
if Canceled then TextStream.Clear;
DoEnd(Self);
end;
end;
function TBase64.ByteFromTable(Ch : Char) : byte;
var
i : byte;
begin
i:=1;
while (Ch<>Table[i]) and (i<=64) do Inc(i);
if i>64 then
begin
if Ch='=' then Result:=0
else raise EUUInvalidCharacter.Create;
end;
Result:=i-1;
end;
procedure TBase64.GenerateBinBytes(InS : string; BufPtr : pointer;
var BytesGenerated : word);
var
i,j,k,b,m : word;
InSLen : byte absolute InS;
ActualLen : byte;
begin
FillChar(BufPtr^,MaxChars,0);
FillChar(A24Bits,SizeOf(T24Bits),0);
k:=0;
for i:=1 to InSLen do
begin
b:=ByteFromTable(InS[i]);
for j:=5 DownTo 0 do
begin
m:=1 shl j;
if (b and m = m) then
A24Bits[k]:=true;
Inc(k);
end;
end;
k:=0;
if InSLen<>4*MaxChars div 3 then
begin
ActualLen:=3*InSLen div 4;
while InS[InSLen]='=' do
begin
Dec(ActualLen);
Dec(InSLen);
end;
end
else
ActualLen:=MaxChars;
for i:=1 to ActualLen do
begin
b:=0;
for j:=7 DownTo 0 do
begin
if A24Bits[k] then b:= b or (1 shl j);
Inc(k);
end;
byte(PChar((PChar(BufPtr)+i-1))^):=b;
end;
BytesGenerated:=i;
end;
procedure TBase64.Decode;
var
ATxtBytes : TTxtBytes;
BytesGenerated : word;
Total : LongInt;
s : string;
p : pointer;
{$IFNDEF UseHuge}
i : LongInt;
{$ENDIF}
begin
DoStart(Self);
Progress:=0;
Canceled:=false;
{$IFNDEF UseHuge}
i:=0;
{$ENDIF}
try
GetMem(p,MaxChars);
Total:=0;
repeat
FillChar(p^,MaxChars,0);
{$IFDEF UseHuge}
TextStream.Read(s);
{$ELSE}
s:=TextStream[i];
{$ENDIF}
GenerateBinBytes(s,p,BytesGenerated);
Stream.Write(p^,BytesGenerated);
Inc(Total,BytesGenerated);
{$IFDEF UseHuge}
Progress:=Round(100*Total/TextStream.Size);
{$ELSE}
Progress:=Round(100*i/(TextStream.Count-1));
{$ENDIF}
if Progress mod ProgressStep = 0 then
DoProgress(Self);
Application.ProcessMessages;
{$IFDEF UseHuge}
until (TextStream.Position>=TextStream.Size) or Canceled;
{$ELSE}
Inc(i);
until (i>=TextStream.Count);
{$ENDIF}
finally
Progress:=100;
DoProgress(Self);
FreeMem(p,MaxChars);
DoEnd(Self);
end;
end;
{implementation for TQuotedPrintable}
const
BufSize=$6000;
constructor TQuotedPrintable.Create(AStream : TStream; ALines : TStringList);
begin
Stream:=AStream;
Lines:=ALines;
Canceled:=false;
end;
procedure TQuotedPrintable.ReplaceHiChars(var s : string);
var
sLen : byte absolute s;
i : byte;
begin
i:=1;
while i<sLen do
begin
if Ord(s[i]) in [0..31,61,